using System.Xml;
using System.Xml.Serialization;
using NalogGarLoader.Model.GarRepositoryReader;
using System.Diagnostics;
using LinqToDB;
using NalogGarLoader.Data;
using LinqToDB.Data;
using System.Collections;
using NalogGarLoader.Data.Tables.GarEntries;

namespace NalogGarLoader.Model;

public class GarFileImporter : IDisposable
{
    protected GarRepositoryEntry RepositoryEntry { get; }
    protected GarDbContext GarDbContext { get; }
    protected Type GarEntryType { get; init; }
    public uint RecordsImported { get; protected set; }

    public GarFileImporter(GarRepositoryEntry repositoryEntry)
    {
        this.RepositoryEntry = repositoryEntry;
        this.GarDbContext = new GarDbContext();
        this.GarEntryType = GarTypes.GarTypeMapping[this.RepositoryEntry.GarType];
    }

    public uint Import()
    {
        using Stream stream = this.RepositoryEntry.GetStreamDelegate.Invoke(this.RepositoryEntry);
        GarXmlFileParser garXmlFileParser = new(stream, this.GarEntryType);

        foreach (GarEntryBase garEntry in garXmlFileParser.Parse())
        {
            garEntry.GarVersion = this.RepositoryEntry.GarVersion;

            if (garEntry is GarAddressTableEntryBase)
            {
                var garTableEntry = (GarAddressTableEntryBase)garEntry;
                garTableEntry.StateId = this.RepositoryEntry.StateId;
            }

            this.InsertEntry(garEntry);
            this.RecordsImported++;
        }

        this.OnEndImport();

        return this.RecordsImported;
    }

    protected virtual void OnEndImport()
    {
        
    }

    protected virtual void InsertEntry(GarEntryBase garEntry)
    {
        this.GarDbContext.InsertOrReplace(tableType: this.GarEntryType, obj: garEntry);
    }

    public void Dispose()
    {
        this.GarDbContext.Dispose();
    }

    public static GarFileImporter Create(GarRepositoryEntry repositoryEntry, GarImportParameters importParameters)
    {
        GarFileImporter? garFileImporter = null;

        if(importParameters.InsertMode == InsertMode.Insert)
            garFileImporter = new GarFileBulkImporter(repositoryEntry, importParameters.BulkInsertBufferSize);
        else
            garFileImporter = new GarFileImporter(repositoryEntry);

        return garFileImporter;
    }
}